package com.tmxk.jdbc;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 *  使用JDBC连接数据库步骤
 *  1. 导入对应的数据库驱动jar包
 *  2. 加载数据库驱动
 *  3. 建立数据库连接
 *  4. 执行sql语句
 *  5. 遍历查询的数据结果集(rs结果集)
 *  6. 释放所有数据库连接资源
 */
public class ConnDBOrclEmp {
    //使用静态常量标识 数据库连接路径、 用户名 、 用户密码
    protected static final String URL = "jdbc:oracle:thin:@127.0.0.1:1521:orcl";
    protected static final String USERNAME = "scott";
    protected static final String PASSWORD = "scott";
    // 定义公共的数据连接对象、 动态执行sql语句传输通道、 rs结果集
    protected Connection conn = null;
    protected PreparedStatement pstmt = null;
    protected ResultSet rs = null;

    static {
        // 应用了反射机制,使用Class.forName(Driver) 加载数据库驱动
        try {
            Class.forName("oracle.jdbc.driver.OracleDriver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 建立数据库连接方法
     * @return 数据库连接信息
     */
    public Connection getConnection(){
        try {
            return DriverManager.getConnection(URL,USERNAME,PASSWORD);
        } catch (SQLException throwables) {
           // throwables.printStackTrace();   // 该方式是抛出异常堆栈信息
            System.out.println("数据库连接异常,异常原因为:" + throwables.getMessage());
        }
        return null;
    }
    //    EMPNO                                              NOT NULL NUMBER(4)
    //    ENAME                                              VARCHAR2(10)
    //    JOB                                                VARCHAR2(9)
    //    MGR                                                NUMBER(4)
    //    HIREDATE                                           DATE
    //    SAL                                                NUMBER(7,2)
    //    COMM                                               NUMBER(7,2)
    //    DEPTNO                                             NUMBER(2)
    /**
     * 查询 Emp 表数据
     */
    public List<Emp> showEmp(){
        // 定义List集合对象,用来存储Emp对象
        List<Emp> empList = new ArrayList<>();
        Emp emp = null;
        //1. 调用数据库连接方法
        conn =  getConnection();
        //2. 定义查询emp的sql语句
        String sql = " select EMPNO, ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO from emp ";
        try {
            // 3. 建立数据库连接通道, 传输sql语句
            pstmt = conn.prepareStatement(sql);
            // 4. 触发执行查询sql语, 并使用rs结果集接收
            rs = pstmt.executeQuery();
            // 5. 循环遍历 rs 结果集
            while(rs.next()){
                int empNo = rs.getInt("EMPNO");
                String eName = rs.getString("ENAME");
                String job = rs.getString("JOB");
                int mgr = rs.getInt("MGR");
                Date hireDate = rs.getDate("HIREDATE");
                double sal = rs.getDouble("SAL");
                double comm = rs.getDouble("COMM");
                int deptNo = rs.getInt("DEPTNO");
                emp = new Emp(empNo,eName,job,mgr,hireDate,sal,comm,deptNo);
                empList.add(emp);
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            // 释放所有资源
            try {
                if( rs != null){
                    rs.close();
                }
                if( pstmt!= null ){
                    pstmt.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        return empList;
    }

    /**
     * 根据指定编号查询对应雇员信息是否存在
     * @param empNo 参数条件,雇员编号
     * @return  雇员信息
     */
    public Emp queryEmpByEmpNo(int empNo){
        // 创建Emp对象
        Emp emp = null;
        // 1. 连接数据库
        conn = getConnection();
        //2. 定义查询sql语句
        String sql = "select EMPNO, ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO from emp  where EMPNO = ? " ;
        try {
            //3. 建立数据传输通道,传输预编译的sql语句
            pstmt =  conn.prepareStatement(sql);
            //4. 设置预编译sql语句中的动态参数
            pstmt.setInt(1,empNo);
            // 5. 触发执行sql语句
            rs = pstmt.executeQuery();
            // 6. 遍历rs结果集
            if (rs.next()){
                emp = new Emp();
                // 使用set赋值
                emp.setEmpNo(rs.getInt("EMPNO"));
                String empName = rs.getString("ENAME");
                emp.seteName(empName);
                emp.setJob(rs.getString("JOB"));
                emp.setMgr(rs.getInt("MGR"));
                emp.setHireDate(rs.getDate("HIREDATE"));
                emp.setSal(rs.getDouble("SAL"));
                emp.setComm(rs.getDouble("COMM"));
                emp.setDeptNo(rs.getInt("DEPTNO"));
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            //释放所有连接资源
            try{
                if(rs != null){
                    rs.close();
                }
                if(pstmt != null){
                    pstmt.close();
                }
                if(conn != null){
                    conn.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        return emp;
    }

    /**
     * 新增 Emp 雇员信息
     * @return 添加雇员信息是否成功受影响的行数
     */
    public int addEmp(Emp emp){
        int addResult = 0;
        //1.连接数据库
        conn = getConnection();
        //2. 定义添加Emp表的sql语句
        String sql = "insert into emp(EMPNO, ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO ) " +
                  " values(seq_emp_no.nextval,?,?,?, sysdate,?,?,?) ";
        try {
            //3. 建立数据库连接通道,传输sql语句
            pstmt = conn.prepareStatement(sql);
            //4. 使用PrepareStatement对象提供的 设置参数占位符的方式 进行动态传参
            pstmt.setString(1,emp.geteName());
            pstmt.setString(2,emp.getJob());
            pstmt.setInt(3,emp.getMgr());
            pstmt.setDouble(4,emp.getSal());
            pstmt.setDouble(5,emp.getComm());
            pstmt.setInt(6,emp.getDeptNo());
            //5. 触发执行DML操作的sql语句,并返回受影响的行数
            addResult = pstmt.executeUpdate();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            try {
                if (pstmt != null) {
                    pstmt.close();
                }
                if(conn != null){
                    conn.close();
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        return addResult;
    }

    // update emp set sal = sal + ?,comm = ? where empno = ?
  //  public int update(double sal, double comm, int empNo){}
    /**
     * 修改雇员信息
     * @param emp 修改对象参数及条件
     * @return 是否修改成功受影响的行数
     */
    public int updateEmp(Emp emp){
        //定义一个变量,用来接收受更新影响的行数
        int updateResult = 0;
        //1.连接数据库
        conn = getConnection();
        // 定义update更新sql
        String sql = "update emp set sal = sal + ?,comm = ? where empno = ? ";
        try {
            // 2. 建立数据库连接通道,并传输sql语句
            pstmt = conn.prepareStatement(sql);
            // ? 占位符 , 用来传输动态参数
            //3.根据预编译sql语句,设置动态参数
            pstmt.setDouble(1,emp.getSal());
            pstmt.setDouble(2,emp.getComm());
            pstmt.setInt(3,emp.getEmpNo());
            // 4. 触发执行预编译sql语句
            updateResult = pstmt.executeUpdate();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            // 释放所有资源
            try{
                if(pstmt!=null){
                    pstmt.close();
                }
                if(conn != null){
                    conn.close();
                }
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
        return updateResult;
    }

    /**
     * 删除指定雇员编号信息
     * @param empNo 删除条件参数,雇员编号
     * @return 是否删除成功受影响的行数
     */
    public int deleteEmp(int empNo){
        // 定义一个变量,用来标识删除是否成功受影响的行数
        int deleteResult = 0;
        //1. 连数据库
        conn = getConnection();
        //2. 定义删除的sql语句
        String sql = " delete from emp where empno = ? ";
        try {
            //3. 建立数据库连接通道,传输sql语句
            pstmt = conn.prepareStatement(sql);
            //4.设置预编译sql语句中的动态参数
            pstmt.setInt(1,empNo);
            //5.触发执行sql语句
            deleteResult = pstmt.executeUpdate();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            try {
                //6.释放所有资源
                if(pstmt != null){
                    pstmt.close();
                }
                if(conn != null){
                    conn.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        return deleteResult;
    }
}














